package Concurrency2.Chapter03_CAS_Atomic.P01_CASUsage;

import Concurrency2.Chapter03_CAS_Atomic.Utils4Unsafe;
import sun.misc.Unsafe;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 测试内容: 自增测试
 * 1, 使用内置锁
 * 2, 使用CAS
 * <p>
 * 10个线程, 每个自增1000万次
 */
public class T04_PerformanceTesting {
    private static int TEN_MILLION = 10000000;
    private static int TURN = 10;

    public static void main(String[] args) {
        countWithLock();
        countWithCAS();
    }

    private static void countWithLock() {
        long start = System.currentTimeMillis();
        Object lock = new Object();
        SomeData someData = new SomeData();
        CountDownLatch countDownLatch = new CountDownLatch(TURN);
        // 任务定义
        Runnable task_AutoIncrement = () -> {
            //内置锁方式
            for (int i = 0; i < TEN_MILLION; i++) {
                synchronized (lock) {
                    someData.data++;
                }
            }
            countDownLatch.countDown();
        };
        // 开启TURN个线程并提交任务给线程池, 函数内部主线程等待所有任务执行完成
        submitTask(task_AutoIncrement, countDownLatch);
        //主线程执行等待
        long end = System.currentTimeMillis();
        // 输出使用内置锁的执行结果
        System.out.println("Result_lock: " + someData.data);
        System.out.println("TimeWasted_lock: " + (end - start));
    }

    private static void countWithCAS() {
        long start = System.currentTimeMillis();

        SomeData someData = new SomeData();
        CountDownLatch countDownLatch = new CountDownLatch(TURN);
        // 获取Unsafe
        Unsafe unsafe = Utils4Unsafe.getUnsafe();
        // 获取待修改属性的offset
        long dataOffset;
        try {
            dataOffset = unsafe.objectFieldOffset(SomeData.class.getDeclaredField("data"));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        // 定义线程任务
        Runnable task_AutoIncrement = () -> {
            for (int i = 0; i < TEN_MILLION; i++) {
                int oldData = someData.data;
                while (!unsafe.compareAndSwapInt(someData, dataOffset, oldData, oldData + 1)) {
                    oldData = someData.data;
                }
            }
            countDownLatch.countDown();
        };
        // 提交线程任务, 函数内部主线程等待所有任务执行完成
        submitTask(task_AutoIncrement, countDownLatch);
        long end = System.currentTimeMillis();
        // 输出使用内置锁的执行结果
        System.out.println("Result_cas: " + someData.data);
        System.out.println("TimeWasted_cas : " + (end - start));
    }

    /**
     * 提交任务给
     *
     * @param task
     */
    private static void submitTask(Runnable task, CountDownLatch countDownLatch) {
        ExecutorService threadPool = Executors.newFixedThreadPool(TURN);
        for (int i = 0; i < TURN; i++) {
            threadPool.submit(task);
        }
        try {
            // 等待所有的线程任务执行完毕
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 关闭线程池
        threadPool.shutdownNow();
    }

    static class SomeData {
        protected int data;
    }
}
